﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using GCC.APIContainer.Utilities;
using GCC.Container.Abstracts;

using Microsoft.AspNetCore.Mvc;

using tcm.entity;
using tcm.Filters;
using tcm.response;
using tcm.utils;

using WxPayAPI;

namespace tcm.Controller
{
    [Route("tcm/wxpay")]
    public class WxPayController : GCCAPIControllerBase
    {
        public WxPayController(AbsGCCContext context) : base(context)
        {

        }

        [HttpGet("url")]
        [TCMAuth(permission: "facility")]
        public WxPayUrlRes getWxPayUrl(long orderId) 
        {
            WxPayUrlRes res = new WxPayUrlRes();
            res.id = orderId;
            res.code = GlobalConstant.Success;

            List<Order> list = GCCEntrance.DBManager.GlobalDB.Select<Order>()
                .Where(a => a.id == orderId)
                .Where(a => a.pay_status == 0 || a.pay_status == 2).ToList();
            if (list == null || list.Count == 0) 
            {
                res.code = GlobalConstant.Failure;
                res.msg = "没有需要支付的订单信息！";
                return res;
            }

            Order order = list.First();
            int fee = getFee(order.price);
            if (fee < 1) 
            {
                res.code = GlobalConstant.Failure;
                res.msg = "金额小于1分钱！";
                return res;
            }

            string notifyUrl = Environment.GetEnvironmentVariable("notifyUrl") ?? "";
            if (String.IsNullOrEmpty(notifyUrl))
            {
                res.code = GlobalConstant.Failure;
                res.msg = "notifyUrl环境变量配置为空！";
                return res;
            }
            //随机字符串
            string out_trade_no = WxPayApi.GenerateOutTradeNo();

            WxPayData data = new WxPayData();
            data.SetValue("body", "test");//商品描述
            //data.SetValue("attach", "test");//附加数据
            data.SetValue("out_trade_no", out_trade_no);
            data.SetValue("total_fee", fee);//总金额
            data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
            data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间
            //data.SetValue("goods_tag", "jjj");//商品标记
            data.SetValue("trade_type", "NATIVE");//交易类型
            data.SetValue("product_id", order.id.ToString());//商品ID
            data.SetValue("notify_url", "notifyUrl" + "​/tcm​/wxpay​/paynotify");

            WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
            res.msg = "返回支付码url成功！";
            string url = result.GetValue("code_url").ToString();//获得统一下单接口返回的二维码链接
            res.url = url;

            // 订单状态改成待支付
            order.pay_status = 2;
            order.out_trade_no = out_trade_no;
            int m = GCCEntrance.DBManager.GlobalDB.Update<Order>(order.id).SetSource(order).ExecuteAffrows();
            if (m <= 0)
            {
                res.code = GlobalConstant.Failure;
                res.msg = "更新订单状态失败！";
            }
            return res;
        }

        [HttpGet("order")]
        [TCMAuth(permission: "facility")]
        public Result queryOrder(long? orderId) 
        {
            Result res = new Result();
            res.code = GlobalConstant.Success;

            // 查询所有待支付的数据
            List<Order> list = GCCEntrance.DBManager.GlobalDB.Select<Order>()
                .Where(a => a.pay_status == 2).WhereIf(orderId != null, a => a.id == orderId).ToList();
            if (list == null || list.Count == 0) 
            {
                res.msg = "无待支付订单！";
            }

            for (int i = 0; i < list.Count; i++)
            {
                // 订单信息
                Order order = list[i];

                WxPayData queryOrderInput = new WxPayData();
                queryOrderInput.SetValue("out_trade_no", list[i].out_trade_no);
                WxPayData result = WxPayApi.OrderQuery(queryOrderInput);

                if (result.GetValue("return_code").ToString() == "SUCCESS"
                    && result.GetValue("result_code").ToString() == "SUCCESS")
                {
                    //支付成功
                    if (result.GetValue("trade_state").ToString() == "SUCCESS")
                    {
                        _ =GCCEntrance.DBManager.GlobalDB.Update<Order>(order.id).Set(a => a.pay_status == 1).Set(a => a.pay_date == DateTime.Now).ExecuteAffrows();
                    }
                }else if (result.GetValue("err_code").ToString() == "ORDERNOTEXIST")
                {
                    // //如果返回错误码为“此交易订单号不存在”则直接认定失败 支付异常
                    _ = GCCEntrance.DBManager.GlobalDB.Update<Order>(order.id).Set(a => a.pay_status == 3).ExecuteAffrows();
                }
            }

            res.msg = "所有待支付订单已确认完毕！";
            return res;
        }

        [HttpPost("payNotify")]
        public String payNotify([FromBody] string xml)
        {
            //Logger.Information(String.Format("payNotify,xml：{0}", xml));
            string payNotifyResult = "";
            try
            {
                WxPayData wxPayData = new WxPayData();
                SortedDictionary<string, object> result = wxPayData.FromXml(xml);
                string order_no = result["out_trade_no"].ToString();

                string sign = result["sign"].ToString();
                string total_fee = result["total_fee"].ToString();

                // 签名未校验

                List<Order> list = GCCEntrance.DBManager.GlobalDB.Select<Order>()
                   .Where(a => a.out_trade_no == order_no)
                   .Where(a => a.pay_status == 2).ToList();
                if (list != null && list.Count > 0)
                {
                    Order order = list[0];
                    if (getFee(order.price) == int.Parse(total_fee))
                    {
                        _ = GCCEntrance.DBManager.GlobalDB.Update<Order>(order.id).Set(a => a.pay_status == 1).Set(a => a.pay_date == DateTime.Now).ExecuteAffrows();
                    }
                    else
                    {
                        //Logger.Error("信返回账单金额和数据库账单金额对不上");
                        throw new WxPayException("微信返回账单金额和数据库账单金额对不上！");
                    }
                }
                else
                {
                    //Logger.Error("没有有效的待支付订单！");
                    throw new WxPayException("没有有效的待支付订单！");
                }

                payNotifyResult = order_no + sign + total_fee;

            }
            catch (Exception ex) 
            {
                //Logger.Error(String.Format("payNotify Exception：{0}", ex.Message));
                throw new WxPayException("payNotify Exception " + ex.Message);
            }

            return payNotifyResult;
        }

        // 微信支付入参金额单位为分
        private int getFee(double price) 
        {   
            try
            {
                price *= 100;
                return (int)price;
            }
            catch (Exception ex) 
            {
                Log.Error("WxPayController.getFee", "getFee Error, price:" + price + " " + ex.ToString());
                return 0;
            }
            
        }
    }
}
